package wang.java.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * not thread safe
 *
 * @author wang
 */
public class MarkdownBuilder implements Serializable {
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

    private final StringBuilder builder = new StringBuilder();

    public MarkdownBuilder append(String content) {
        builder.append(content);
        return this;
    }

    public MarkdownBuilder appendLine(String content) {
        builder.append(content).append(LINE_SEPARATOR);
        return this;
    }

    public MarkdownBuilder appendTitle(String title, int level) {
        if (level <= 0 || level > 6) {
            throw new IllegalArgumentException("level must be in [1,6]");
        }

        IntStream.range(0, level).forEach(i -> builder.append("#"));
        builder.append(" ");
        return appendLine(title);
    }

    public MarkdownBuilder appendCode(String singleLineCode) {
        builder.append('`').append(singleLineCode).append('`');
        return this;
    }

    public MarkdownBuilder appendCodeBlock(String multiLineCode) {
        return appendCodeBlock(multiLineCode, "java");
    }

    public MarkdownBuilder appendCodeBlock(String multiLineCode, String language) {
        builder.append("```").append(language).append(LINE_SEPARATOR).append(multiLineCode).append("```").append(LINE_SEPARATOR);
        return this;
    }

    @Override
    public String toString() {
        return builder.toString();
    }

    public void toFile(String path, String name) {
        File file = new File(path + File.separator + name + ".md");
        try {
            file.delete();
            file.createNewFile();
            try (FileWriter fileWriter = new FileWriter(file)) {
                fileWriter.write(toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public MarkdownBuilder appendTable(List<List<String>> table) {
        return appendTable(table, Alignment.MIDDLE, true);
    }

    public MarkdownBuilder appendTable(List<List<String>> table, Alignment alignment, boolean containsHeader) {
        int row = table.size();
        if (0 == row) {
            return this;
        }
        int col = table.get(0).size();
        if (0 == col) {
            return this;
        }
        if (containsHeader) {
            append("|").append(String.join("|", table.get(0))).appendLine("|");
        } else {
            append("|").append(IntStream.range(0, col).mapToObj(i -> " ").collect(Collectors.joining("|"))).appendLine("|");
        }
        append("|").append(IntStream.range(0, col).mapToObj(i -> alignment.getDesc()).collect(Collectors.joining("|"))).appendLine("|");
        for (int i = containsHeader ? 1 : 0; i < row; i++) {
            append("|").append(String.join("|", table.get(i))).appendLine("|");
        }
        return this;
    }

    public MarkdownBuilder appendList(String content, int indent) {
        return appendList(content, indent, 0);
    }

    public MarkdownBuilder appendList(String content, int indent, int order) {
        if (indent < 0) {
            throw new IllegalArgumentException("indent不能为负");
        }

        IntStream.range(0, indent).forEach(i -> append("  "));

        if (order <= 0) {
            // 无序列表
            appendLine("+ " + content);
        } else {
            appendLine(order + ". " + content);
        }
        return this;
    }

    public enum Alignment {
        LEFT("--"),
        MIDDLE(":--:"),
        RIGHT("--:");

        private String desc;

        Alignment(String desc) {
            this.desc = desc;
        }

        public String getDesc() {
            return desc;
        }
    }
}
